package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import com.zzyl.constant.RecourseCacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceListDto;
import com.zzyl.dto.addResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.MenuMetaVo;
import com.zzyl.vo.MenuVo;
import com.zzyl.vo.TreeItemVo;
import com.zzyl.vo.TreeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ResourceServiceImpl implements ResourceService {
    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    @Cacheable(cacheNames = RecourseCacheConstant.LIST,key = "#dto.hashCode()")
    public List<Resource> getResourceList(ResourceListDto dto) {
        return resourceMapper.getResourceList(dto);
    }

    @Override
    @Cacheable(cacheNames = RecourseCacheConstant.TREE,key = "''")
    public TreeVo getResourceTree() {
        // 查询出拉平的所有的菜单， data_state=0 resource_type=m parent_resource_no like 100001%
        String dataState = SuperConstant.DATA_STATE_0;
        String resourceType = SuperConstant.MENU;
        String parentResourceNo = NoProcessing.processString(SuperConstant.ROOT_PARENT_ID);
        List<Resource> resourceList = resourceMapper.getResourceTree(dataState, resourceType, parentResourceNo);
        log.info(resourceList.toString());

        TreeVo treeVo = new TreeVo();
        //创造根节点
        TreeItemVo rootItem = new TreeItemVo();
        rootItem.setId(SuperConstant.ROOT_PARENT_ID);
        rootItem.setLabel(SuperConstant.ROOT_PARENT_LABEL);

        if(CollectionUtils.isEmpty(resourceList)){
            return treeVo;
        }
        //把List<Resource>类型的集合，转为List<TreeItemVo>
        List<TreeItemVo> treeItemVoList = resourceToItemVo(resourceList);
        //把List<TreeItemVo>类型的集合重构成树形集合
        buildTree(rootItem,treeItemVoList);
        treeVo.setItems(List.of(rootItem));
        return treeVo;
    }

    @Override
    @Caching(
            evict = {
                    @CacheEvict(cacheNames = RecourseCacheConstant.TREE,key = "''"),
                    @CacheEvict(cacheNames = RecourseCacheConstant.LIST,allEntries = true)
            }
    )
    public void addResource(addResourceDto dto) {
        Resource resource = BeanUtil.copyProperties(dto, Resource.class);
        //判断是不是按钮
        boolean isButton = Objects.equals(dto.getResourceType(), SuperConstant.BUTTON);
        //判断父菜单是否超多3级
        String s = NoProcessing.processString(dto.getParentResourceNo());
        if(!isButton&&s.length()>16){
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        //查库判断父菜单是否有子菜单，此时查最大的子菜单，方便以后使用
        Resource maxChildren = resourceMapper.getMaxChildren(dto);
        // 生成resource_no
        String resourceNo = null;
        if(maxChildren==null){
            //没有子菜单,父菜单的编号+001
            resourceNo = NoProcessing.createNo(dto.getParentResourceNo(),false);
        }else {
            //有子菜单
            resourceNo = NoProcessing.createNo(maxChildren.getResourceNo(),false);
        }
        resource.setResourceNo(resourceNo);
        resourceMapper.insertSelective(resource);
    }

    @Override
    public List<Resource> getAllResourceById(Long userId) {
        return resourceMapper.getAllResourceById(userId);
    }

    @Override
    public List<MenuVo> getMenuResourceByUserId(Long userId) {
        //先根据id查询所有用户菜单
        List<Resource> menuResourceList = resourceMapper.getMenuResourceByUserId(userId,SuperConstant.DATA_STATE_0,SuperConstant.MENU);
        if(CollectionUtils.isEmpty(menuResourceList)){
            return new ArrayList<>();
        }
        List<MenuVo> menuVoList = new ArrayList<>();
        //组装一下数据
        for (Resource resource : menuResourceList) {
            MenuVo menuVo = BeanUtil.copyProperties(resource, MenuVo.class);
            menuVo.setName(resource.getResourceName());
            menuVo.setPath(resource.getRequestPath());
            menuVo.setRedirect("/"+resource.getResourceName());
            menuVo.setChildren(new ArrayList<>());
            menuVo.setMeta(new MenuMetaVo(resource.getResourceName(),resource.getIcon()));
            menuVoList.add(menuVo);
        }
        //创建根节点
        MenuVo parent = new MenuVo();
        parent.setResourceNo(SuperConstant.ROOT_PARENT_ID);
        parent.setChildren(new ArrayList<>());
        //组装树形结构
        buildTree(parent,menuVoList);
        return parent.getChildren();
    }

    @Override
    public List<String> getAllResourceLabelByPath(List<String> publicAccessUrls) {
        return resourceMapper.getAllResourceLabelByPath(publicAccessUrls);
    }

    private void buildTree(MenuVo parent, List<MenuVo> menuVoList){
        for (MenuVo menuVo : menuVoList) {
            if(Objects.equals(menuVo.getParentResourceNo(),parent.getResourceNo())){
                parent.getChildren().add(menuVo);
                buildTree(menuVo,menuVoList);
            }
        }
    }



    private void buildTree(TreeItemVo rootItem, List<TreeItemVo> treeItemVoList) {
        for (TreeItemVo treeItemVo : treeItemVoList) {
            if(Objects.equals(rootItem.getId(), treeItemVo.getParentId())){
                rootItem.getChildren().add(treeItemVo);
                buildTree(treeItemVo,treeItemVoList);
            }
        }
    }

    private List<TreeItemVo> resourceToItemVo(List<Resource> resources) {
        ArrayList<TreeItemVo> treeItemVos = new ArrayList<>();
        for (Resource resource : resources) {
            TreeItemVo treeItemVo = new TreeItemVo();
            treeItemVo.setId(resource.getResourceNo());
            treeItemVo.setLabel(resource.getResourceName());
            treeItemVo.setParentId(resource.getParentResourceNo());
            treeItemVo.setChildren(new ArrayList<>());
            treeItemVos.add(treeItemVo);
        }
        return treeItemVos;
    }

}
